package application.common.plugins.mqtt;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import com.jfinal.ext.kit.DateKit;
import com.jfinal.plugin.IPlugin;

public class Mqttv3Plugin implements IPlugin {

	private String HOST = "tcp://localhost:1883";
	private String clientid = UUID.randomUUID().toString();
	private MqttClient client;
	private MqttConnectOptions options;
	private String userName = "admin";
	private String passWord = "admin";
	private String SUBSCRIBE_TOPIC = "cabinet/server";
	private String PUBLISH_TOPIC = "cabinet/client";
	private MqttTopic topic;
	
	public Mqttv3Plugin() {
	}
	
	public Mqttv3Plugin(String clientid) {
		this.clientid=clientid;
	}

	@Override
	public boolean start() {
		init();
		return true;
	}

	@Override
	public boolean stop() {
		try {
			client.close();
			scheduler.shutdown();
			schedulerInit.shutdown();
		}catch (Exception e) {
		}
		return false;
	}

	public boolean init() {
		try {
			client = new MqttClient(HOST, clientid, new MemoryPersistence());
			// MQTT的连接设置
			options = new MqttConnectOptions();
			// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，这里设置为true表示每次连接到服务器都以新的身份连接
			options.setCleanSession(false);
			// 设置连接的用户名
			options.setUserName(userName);
			// 设置连接的密码
			options.setPassword(passWord.toCharArray());
			// 设置超时时间 单位为秒
			options.setConnectionTimeout(10);
			// 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线，但这个方法并没有重连的机制
			options.setKeepAliveInterval(20);
			// 设置回调
			client.setCallback(new MqttCallback() {
				@Override
				public void connectionLost(Throwable cause) {
					reconnect();
				}
				@Override
				public void messageArrived(String topic, MqttMessage message) throws Exception {
					// subscribe后得到的消息会执行到这里面
					System.out.println("接收消息主题:" + topic);
					System.out.println("接收消息Qos:" + message.getQos());
					System.out.println("接收消息内容:" + new String(message.getPayload()));
				}

				@Override
				public void deliveryComplete(IMqttDeliveryToken token) {
					System.out.println("deliveryComplete---------" + token.isComplete());
				}

			});
			topic = client.getTopic(SUBSCRIBE_TOPIC);
			options.setWill(topic, "close".getBytes(), 0, true);
			client.connect(options);
			int[] Qos = { 1 };
			String[] topic1 = { SUBSCRIBE_TOPIC };
			client.subscribe(topic1, Qos);
			return true;
		} catch (Exception e) {
			try {
				client.close();
			} catch (MqttException e1) {
			}
			e.printStackTrace();
			client = null;
			reInit();
		}
		return false;
	}

	private ScheduledExecutorService scheduler;

	// 重新链接
	public void reconnect() {
		if (scheduler == null) {
			scheduler = Executors.newSingleThreadScheduledExecutor();
			scheduler.scheduleAtFixedRate(new Runnable() {
				public void run() {
					if (!client.isConnected()) {
						try {
							System.out.println("---------reconnect-start-----------");
							client.connect(options);
							System.out.println("---------reconnect-end-ok-----------");
						} catch (MqttSecurityException e) {
							System.out.println("---------reconnect-end-MqttSecurityException-----------");
						} catch (MqttException e) {
							System.out.println("---------reconnect-end-MqttException-----------");
						}
					}
				}
			}, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS);
		}
	}

	private ScheduledExecutorService schedulerInit;
	public void reInit() {
		if (schedulerInit == null) {
			schedulerInit = Executors.newSingleThreadScheduledExecutor();
			schedulerInit.scheduleAtFixedRate(new Runnable() {
				public void run() {
					if (client == null) {
						init();
					}
				}
			}, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS);
		}
	}
	
	public void publish(String payload ) {
		if(client!=null && client.isConnected()) {
			try {
				MqttMessage message = new MqttMessage();  
		        message.setQos(1);  
		        message.setRetained(true);  
		        message.setPayload(payload.getBytes());
		        client.publish(PUBLISH_TOPIC, message);
			}catch (Exception e) {
			}
		}
	}
	

	public static void main(String[] args) {
		Mqttv3Plugin d = new Mqttv3Plugin();
		d.start();
		
		
		ScheduledExecutorService schedulerInit = Executors.newSingleThreadScheduledExecutor();
		schedulerInit.scheduleAtFixedRate(new Runnable() {
			public void run() {
				d.publish(DateKit.toStr(new Date(System.currentTimeMillis()), "yyyy-MM-dd hh:mm:ss"));
			}
		}, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS);
		
		
		
	}

}
